package com.duolebo.uteped_sdk.ota.jl;


import android.annotation.SuppressLint;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.util.Log;

import com.duolebo.uteped_sdk.UTEPedBleClientHelper;
import com.duolebo.uteped_sdk.ota.BaseOemOta;
import com.duolebo.uteped_sdk.ota.BleOtaListener;
import com.duolebo.uteped_sdk.utils.Const;
import com.duolebo.uteped_sdk.utils.DeviceHelper;
import com.duolebo.uteped_sdk.utils.SPHelper;
import com.jieli.jl_bt_ota.constant.ErrorCode;
import com.jieli.jl_bt_ota.interfaces.BtEventCallback;
import com.jieli.jl_bt_ota.interfaces.IActionCallback;
import com.jieli.jl_bt_ota.interfaces.IUpgradeCallback;
import com.jieli.jl_bt_ota.model.BluetoothOTAConfigure;
import com.jieli.jl_bt_ota.model.base.BaseError;
import com.jieli.jl_bt_ota.model.response.TargetInfoResponse;
import com.jieli.jl_rcsp.constant.StateCode;
import com.yc.nadalsdk.ble.open.UteBleClient;
import com.yc.nadalsdk.listener.BleConnectStateListener;
import com.yc.nadalsdk.listener.GattCallbackListener;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;


public class JieLiOta  extends BaseOemOta implements BleConnectStateListener {
    private final static String TAG = "JieLiOta";
    private static final String ONLY_WRITE_UUID_JLOTA = "0000ae01-0000-1000-8000-00805f9b34fb";
    private static final String ONLY_READ_UUID_JLOTA = "0000ae02-0000-1000-8000-00805f9b34fb";

    private Context mContext;
    private BleOtaListener mBleOtaListener;
    private JlOtaManager otaManager;
    private String mFilePath;
    private String deviceAddress;

    public JieLiOta(Context context) {
        this.mContext = context;
        UTEPedBleClientHelper.shareInstance().addBleConnectStateListener(this);
    }

    private void startOTA(String filePath) {
        otaManager.getBluetoothOption().setFirmwareFilePath(filePath);
        otaManager.startOTA(upgradeCallback);
    }


    private void releaseOtaManager() {
        if (otaManager != null) {
            otaManager.release();
            otaManager = null;
        }
    }

    private void releaseOTA() {
        Log.d(TAG,"releaseOTA");
        releaseOtaManager();
        UteBleClient.getUteBleClient().getUteBleConnection().isJLUpgrade(false);
        DeviceHelper.getInstance().setUpgrading(false);
        UteBleClient.getUteBleClient().getUteBleConnection().setOnGattCallbackListener(null);
    }

    @Override
    public void oemPrepare() {

    }

    @Override
    public void oemStartOTA(String filePath, BleOtaListener listener) {
        UteBleClient.getUteBleClient().getUteBleConnection().setOnGattCallbackListener(mCharacteristicChangedListener);
        releaseOtaManager();
        DeviceHelper.getInstance().setUpgrading(true);
        this.otaManager = new JlOtaManager(mContext);
        myOnBtDeviceConnection(BluetoothProfile.STATE_CONNECTED);

        this.mBleOtaListener = listener;
        this.deviceAddress = UteBleClient.getUteBleClient().getDeviceAddress();
        UteBleClient.getUteBleClient().getUteBleConnection().isJLUpgrade(true);

        mFilePath = filePath;
        BluetoothOTAConfigure bluetoothOption = BluetoothOTAConfigure.createDefault();
        bluetoothOption.setPriority(BluetoothOTAConfigure.PREFER_BLE) //请按照项目需要选择
                .setUseAuthDevice(false) //具体根据固件的配置选择
//                .setUseAuthDevice(!SPDao.getInstance().getJlWatchFaceAuthPass()) //具体根据固件的配置选择
                .setBleIntervalMs(500) //默认是500毫秒
                .setTimeoutMs(3000) //超时时间
                .setMtu(500) //BLE底层通讯MTU值，会影响BLE传输数据的速率。建议用500 或者 270。该MTU值会使OTA库在BLE连接时改变MTU，所以用户SDK需要对此处理。
                .setNeedChangeMtu(false) //不需要调整MTU，建议客户连接时调整好BLE的MTU
                .setUseReconnect(false); //是否自定义回连方式，默认为false，走SDK默认回连方式，客户可以根据需求进行变更
//        bluetoothOption.setFirmwareFilePath(firmwarePath); //设置本地存储OTA文件的路径
//        otaManager.getBluetoothOption().setFirmwareFilePath(firmwarePath);
//        bluetoothOption.setFirmwareFileData(firmwareData);//设置本地存储OTA文件的数据

        otaManager.configure(bluetoothOption); //设置OTA参数
        otaManager.registerBluetoothCallback(mBtEventCallback);
    }

    @Override
    public void oemCancelOTA() {
        if (otaManager != null) {
            otaManager.cancelOTA();
        }
    }

    @Override
    public void oemRelease() {

    }

    @Override
    public void oemBluetoothOff() {
        if (mBleOtaListener != null) {
            mBleOtaListener.onOTAError(0, "Bluetooth OFF");
        }
    }

    private final BtEventCallback mBtEventCallback = new BtEventCallback() {
        @Override
        public void onConnection(BluetoothDevice device, int status) {
            //必须等待库回调连接成功才可以开始OTA操作
            Log.d(TAG, "jlOTA onConnection status = " + status+",isOTA = "+ otaManager.isOTA());
            if (status == StateCode.CONNECTION_OK && otaManager != null) {
                if (otaManager.isOTA()) {
                    return; //如果已经在OTA流程，则不需要处理
                }
                Log.d(TAG, "jlOTA 开始固件升级 mFilePath = " + mFilePath);
                startOTA(mFilePath);
                //1.可以查询是否需要强制升级
                otaManager.queryMandatoryUpdate(new IActionCallback<TargetInfoResponse>() {
                    @Override
                    public void onSuccess(TargetInfoResponse deviceInfo) {
                        //TODO:说明设备需要强制升级，请跳转到OTA界面，引导用户升级固件
                        deviceInfo.getVersionCode(); //设备版本号
                        deviceInfo.getVersionName();  //设备版本名
                        deviceInfo.getProjectCode(); //设备产品ID(默认是0，如果设备支持会改变)
                        //需要看固件是否支持
                        deviceInfo.getUid();  //客户ID
                        deviceInfo.getPid();  //产品ID
                        //进行步骤2
                        Log.d(TAG, "jlOTA queryMandatoryUpdate onSuccess");
                    }

                    @Override
                    public void onError(BaseError baseError) {
                        Log.d(TAG, "jlOTA queryMandatoryUpdate onError = " + baseError.getMessage());
                        /*
                         *可以不用处理，也可以获取设备信息
                         */
                        if (baseError.getCode() == ErrorCode.ERR_NONE && baseError.getSubCode() == ErrorCode.ERR_NONE && otaManager != null) {//没有错误，可以获取设备信息
                            TargetInfoResponse deviceInfo = otaManager.getDeviceInfo();
                            deviceInfo.getVersionCode(); //设备版本号
                            deviceInfo.getVersionName();  //设备版本名
                            deviceInfo.getProjectCode(); //设备产品ID(默认是0，如果设备支持会改变)
                            //需要看固件是否支持
                            deviceInfo.getUid();  //客户ID
                            deviceInfo.getPid();  //产品ID
                            //进行步骤2
                        }
                    }
                });
            }
        }
    };

    private final IUpgradeCallback upgradeCallback = new IUpgradeCallback() {
        @Override
        public void onStartOTA() {
            mBleOtaListener.onOtaStatus(BleOtaListener.OTA_STATE_TRANSFERRING);
        }

        @Override
        public void onNeedReconnect(String s, boolean b) {

        }

        @Override
        public void onProgress(int type, float v) {
            int progress = (int)v;
            if (type == 0) {
                progress = (int) (v / 2);
            }
            else {
                progress = 50 + (int) (v / 2);
            }

            if (mBleOtaListener != null) {
                mBleOtaListener.onOTAProgress(progress);
            }
        }

        @Override
        public void onStopOTA() {
            if (mBleOtaListener != null) {
                mBleOtaListener.onOtaStatus(BleOtaListener.OTA_STATE_TRANSFERRED);
            }
            SPHelper.shareInstance().putAndCommit(Const.JL_OTA_STAGE, false);
            releaseOTA();
        }

        @Override
        public void onCancelOTA() {
            if (mBleOtaListener != null) {
                mBleOtaListener.onOtaStatus(BleOtaListener.OTA_STATE_UNKNOWN);
            }
        }

        @Override
        public void onError(BaseError baseError) {
            releaseOTA();
            if (mBleOtaListener != null) {
                mBleOtaListener.onOTAError(baseError.getCode(), baseError.getMessage());
            }
        }
    };

    public void myOnBtDeviceConnection(int status) {
        if (otaManager != null) {
            otaManager.myOnBtDeviceConnection(status);
        }
    }

    public void myOnReceiveDeviceData(byte[] data) {
        if (otaManager != null) {
            otaManager.myOnReceiveDeviceData(data);
        }
    }

    public GattCallbackListener mCharacteristicChangedListener = new GattCallbackListener() {
        @Override
        public void onConnectionStateChange(int status) {
            Log.d(TAG, "JLOTA onConnectionStateChange status = " + status);
            myOnBtDeviceConnection(status);
        }

        @Override
        public void onCharacteristicChanged(BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic characteristic) {
            final byte[] data = characteristic.getValue();
            if (characteristic.getUuid().equals(UUID.fromString(ONLY_READ_UUID_JLOTA))) {
                myOnReceiveDeviceData(data);
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.d(TAG, "JLOTA onCharacteristicWrite status = " + status);
            if (ONLY_WRITE_UUID_JLOTA.equals(characteristic.getUuid().toString()) && otaManager != null) {
                otaManager.wakeupSendThread();
            }
        }
    };

    @SuppressLint("CheckResult")
    @Override
    public void onConnecteStateChange(int status) {
        switch (status) {
            case BleConnectStateListener.STATE_DISCONNECTED:
                Log.d(TAG, "disconnected");
                if (DeviceHelper.getInstance().isUpgrading() && isJieLi()) {
                    Log.d(TAG, "JieLi device reconnect after 1 second");
                    Flowable.timer(2, TimeUnit.SECONDS).observeOn(AndroidSchedulers.mainThread()).subscribe(s -> {
                        DeviceHelper.getInstance().connect(deviceAddress);//延迟1秒钟后再重连，因为杰理OTA时，先收到了断开蓝牙连接的回调后才收到OTA成功的回调
                    });
                }

                break;
            case BleConnectStateListener.STATE_CONNECTING:
                Log.d(TAG, "connecting");
                break;
            case BleConnectStateListener.STATE_CONNECTED:
                Log.d(TAG, "connected," + UteBleClient.getUteBleClient().getDeviceName() + "," + UteBleClient.getUteBleClient().getDeviceAddress());
                break;
        }
    }


}
